#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "arrstack.h"



void Stack_Print(Stack *);

int Calculate(char *pstr);
int main(int argc,char **argv)
{


	char *pstr=*(argv+1);
	if(argc<2)
	{
	
		printf("please input the str for calculate,like ./arrstack.o '(1+3*2)*2+3' ");

		return 0;
	
	}


	pstr=Remove_Brackets(pstr);


	printf("\n%s\n",pstr);

	printf("\n%d\n",Calculate(pstr));

	return 0;
}


/**
 *
 * 计算后缀表达式的值
 * */
int Calculate(char *pstr)
{



	int num1,num2;
	char numBuf[16]={0};

	Stack stack;

	char *ppStr=pstr,c1=0;

	Stack_Init(&stack,16);

	int CalTwoParam(int param1,int param2,char opt);

	while(*ppStr!=0)
	{
	
		c1=*ppStr++;

		if(isdigit(c1))
                {

                        strncat(numBuf,&c1,1);
                        continue;
                }

	

		switch(c1)
		{
		
			case ',':
							
				if(numBuf[0]!=0)
				{
					Stack_Push(&stack,atoi(numBuf));			
					printf("push ->%d\n",atoi(numBuf));
					numBuf[0]=0;
				
				}
				break;

			case '+':
			case '-':
			case '*':
			case '/':

				if(stack.deepIndex<2)
				{
				
					printf("the stack is not enough");

				
				}
				else{
				
					Stack_Print(&stack);
					num2=Stack_Pop(&stack);
					num1=Stack_Pop(&stack);
					printf("calculate the result\n");					
					Stack_Push(&stack,CalTwoParam(num1,num2,c1));


				}

				break;
		
		
		
		
		}

	
	}


	return Stack_Peek(&stack);
}


int CalTwoParam(int param1,int param2,char opt)
{


	switch(opt)
	{
		case '+':
			return param1+param2;
		case '-':
                        return param1-param2;
		case '*':
                        return param1*param2;
		case '/':
                        return param1/param2;
	
	
	}


	return 0;
}

/**
 *
	 * 1.遇到操作数直接输出
	 * 2.如果操作栈为空直接把操作符压栈
	 * 3.如果栈顶操作符比当前操作符优先，则可以弹出栈，把当前操作符压栈
	 * 4.如果栈顶操作符比当前操作符低级，则把当前操作符压栈
	 * 5.如果遇到了(则把(压栈
	 * 6.如果遇到了),则弹出操作栈只到遇到( (也有出栈 
	 * 
	 *给数字加上,用来间隔数字
 *
 */

char  *Remove_Brackets(char * oldStr)
{


	Stack *pCalStack;//stack for calculate

	Stack optStack;//stack for option

	unsigned  i;
	unsigned len,num_s;
	char c1,c2,*pResult=NULL;


	

	if(oldStr==NULL)
	{
	
		return NULL;
	}


	Stack_Init(&optStack,16);

	len=strlen(oldStr);

	

	//如果这里不是2倍，到时候concat ,的时候就会益处
	pResult=(char *)malloc(sizeof(char)*(len*2));

	char numBuf[15]={0};

	*pResult=0;

	for(i=0;i<len;i++)
	{
	
		c1=*(oldStr+i);	
		if(isdigit(c1))
		{
			
			printf("%c",c1);
			//strncat(pResult,&c1,1);
			strncat(numBuf,&c1,1);
			continue;
		}


		num_s=strlen(numBuf);
		if(num_s>0)
		{
			 strncat(pResult,numBuf,num_s);
			 strncat(pResult,",",1);
			 numBuf[0]=0;
		}
		switch(c1)
		{
		
			case '+':
			case '-':
			case '*':
			case '/':
				
				if(Stack_IS_Empty(&optStack))
				{
					Stack_Push(&optStack,(unsigned)c1);
				
				}
				else
				{
					c2=Stack_Peek(&optStack);

					if(CalculateLevel(c1,c2)>0)
					{
					
						printf("%c",c2);
						strncat(pResult,&c2,1);
						Stack_Pop(&optStack);
						Stack_Push(&optStack,(unsigned)c1);	
					}		
					else if(c2=='(')
					{
						 Stack_Push(&optStack,(unsigned)c1);
					}
					else
					{
						//printf("%c",c1);
						//strncat(pResult,&c1,1);
						Stack_Push(&optStack,(unsigned)c1);
					}
					
					
				
				}

				break;


			case '(':

				Stack_Push(&optStack,(unsigned)c1);
				break;
			case ')':
				
				while(Stack_IS_Empty(&optStack)==0)
				{

				
					c2=Stack_Pop(&optStack);

					if(c2=='(')
					{
						break;
					}


					printf("%c",c2);
					strncat(pResult,&c2,1);
				
				}


				break;
		
		}
		
	}
	
	 

	  num_s=strlen(numBuf);
          if(num_s>0)
           {
                         strncat(pResult,numBuf,num_s);
                         strncat(pResult,",",1);
                         numBuf[0]=0;
          }	
	  while(Stack_IS_Empty(&optStack)==0)
           {

                  c2=Stack_Pop(&optStack);

		  strncat(pResult,&c2,1);

                  printf("%c",c2);


          }
	




	return pResult;

}


/**
 *这个判断就非常非常简单了啊*
 *
 *
 */
unsigned CalculateLevel(char c1,char c2)
{

        if(c1=='+'||c1=='-')
        {
                if(c2=='*'||c2=='/')
                {

                        return 1;
                }

        }

        return 0;

}



void Stack_Print(Stack *pStack)
{
	


	int i=0;
	Item *pItem=NULL;
	if(pStack==NULL)
        {

                printf("the stack is NULL\n");
                return;
        }

	pItem=pStack->pItem;


	while(i<pStack->deepIndex)
	{
	
		
	
		printf("%d\t",*(pItem+i));
		i++;
	}

	printf("\n");

}


void Stack_Init(Stack *pStack,unsigned maxDeep)
{
	
	if(pStack==NULL)
	{
	
		printf("the stack is NULL\n");
		return;
	}


	pStack->pItem=(Item *)malloc(sizeof(Item) *maxDeep);


	if(pStack->pItem==NULL)
	{
	
		printf("alloc the mem error\n");
		return;
	}


	pStack->deepIndex=0;
	pStack->maxDeep=maxDeep;


}




void  Stack_Push(Stack *pStack,Item item)
{


	if(pStack==NULL)
        {

                printf("the stack is NULL\n");
                return;
        }


	if(pStack->deepIndex >= pStack->maxDeep)
	{
	
		printf("the stack is full\n");
		return;
	
	}

	*(pStack->pItem+(pStack->deepIndex)++)=item;
	
	

}



int  Stack_IS_Empty(Stack *pStack)
{

	if(pStack==NULL)
        {

                printf("the stack is NULL\n");
                return 1;
        }


	if(pStack->deepIndex<=0)
        {

                return 1;

        }

	return 0;

}


Item Stack_Peek(Stack *pStack)
{


	if(pStack==NULL)
        {

                printf("the stack is NULL\n");
                return 0;
        }


        if(pStack->deepIndex<=0)
        {

                printf("the stack is empty\n");
                return 0;

        }

        return  *(pStack->pItem+(pStack->deepIndex-1));
}



Item Stack_Pop(Stack* pStack)
{

	 if(pStack==NULL)
        {

                printf("the stack is NULL\n");
                return 0;
        }


	if(pStack->deepIndex<=0)
	{
	
		printf("the stack is empty\n");
		return 0;
	
	}

	return  *(pStack->pItem+(--pStack->deepIndex));

}
